/*
- Garmin GPS Database Reader
+ Garmin GPS Database Reader/Writer
Copyright (C) 2005 Olaf Klein, o.b.klein@t-online.de
Mainly based on mapsource.c,
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
*/
+/*
+ History:
+
+ 2005/06/27: initial release (reader only)
+ 2005/07/26: added write support
+ 2005/07/27: replaced "tricky code" in route reader
+ 2005/07/28: fixed handling of single point routes
+ new option "via"
+ new option "ver"
+ fixed compiler warnings
+*/
+
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MYNAME "gdb"
-#define MPSNAMEBUFFERLEN 1024
-#define MPSNOTESBUFFERLEN 4096
-#define MPSDESCBUFFERLEN 4096
+#undef GDB_DEBUG
+
+#define GDB_VER_MIN 1
+#define GDB_VER_MAX 2
+
+#define GDB_DEFAULTWPTCLASS 0
+#define GDB_HIDDENROUTEWPTCLASS 8
+
+#define GDB_NAME_BUFFERLEN 1024
+#define GDB_NOTES_BUFFERLEN 4096
+#define GDB_DESCR_BUFFERLEN 4096
#define DEFAULTICONVALUE 18
#define DEFAULTICONDESCR "Waypoint"
/* %%% local vars %%% */
-FILE *fin;
-static char *fin_name;
+FILE *fin, *fout;
+static char *fin_name, *fout_name;
+
static int gdb_ver = 1;
static int gdb_debug = 0;
-route_head *gdb_hidden;
+static int gdb_via; /* 0 = read and write hidden points too; 1 = drop */
+static int gdb_category;
+
+route_head *gdb_hidden = NULL;
+
+
+#define GDB_OPT_VER "ver"
+#define GDB_OPT_VIA "via"
+#define GDB_OPT_CATEGORY "cat"
+
+static char *gdb_opt_category = NULL;
+static char *gdb_opt_ver = NULL;
+static char *gdb_opt_via = NULL;
+
+static arglist_t gdb_args[] = {
+ {GDB_OPT_CATEGORY, &gdb_opt_category,
+ "Default category on output (1..16)", NULL, ARGTYPE_INT},
+ {GDB_OPT_VER, &gdb_opt_ver,
+ "Version of gdb file to generate (1,2)", "2", ARGTYPE_INT},
+ {GDB_OPT_VIA, &gdb_opt_via,
+ "Drop route points, if they don't have an aquivalent waypoint (hidden points)", NULL, ARGTYPE_BOOL},
+ {0, 0, 0, 0, 0}
+};
+
+/********************************************************************************************************/
/* %%% 1-1 functions from mapsource, should by shared!!! %%% */
+/*
+ * Add a waypoint that we've already written out to our list
+ *
+ */
+void
+gdb_add_to_hidden(const waypoint *wpt)
+{
+ waypoint *tmp = waypt_dupe(wpt);
+ route_add_wpt(gdb_hidden, tmp);
+}
+
waypoint *
gdb_find_wpt_q_by_name(const queue *whichQueue, const char *name)
{
const char *
gdb_find_desc_from_icon_number(const int icon, garmin_formats_e garmin_format)
{
+ static char custom[] = "Custom 63";
icon_mapping_t *i;
+ if (icon >= 500 && icon <= 563)
+ {
+ snprintf(custom, sizeof(custom), "Custom %d", icon - 500);
+ return &custom[0];
+ }
+
for (i = garmin_icon_table; i->icon; i++) {
switch (garmin_format) {
case MAPSOURCE:
return DEFAULTICONDESCR;
}
+int
+gdb_find_icon_number_from_desc(const char *desc, garmin_formats_e garmin_format)
+{
+ icon_mapping_t *i;
+ int def_icon = DEFAULTICONVALUE;
+ int n;
+
+ if (!desc)
+ return def_icon;
+
+ /*
+ * If we were given a numeric icon number as a description
+ * (i.e. 8255), just return that.
+ */
+ n = atoi(desc);
+ if (n) {
+ return n;
+ }
+
+ for (i = garmin_icon_table; i->icon; i++) {
+ if (case_ignore_strcmp(desc,i->icon) == 0) {
+ switch (garmin_format) {
+ case MAPSOURCE:
+ return i->mpssymnum;
+ case PCX:
+ case GARMIN_SERIAL:
+ return i->pcxsymnum;
+ default:
+ fatal(MYNAME ": unknown garmin format");
+ }
+ }
+ }
+ return def_icon;
+}
+
+int
+gdb_detect_rtept_class(const waypoint *wpt)
+{
+ if (gdb_find_wpt_q_by_name((queue *)&gdb_hidden->waypoint_list, wpt->shortname) == NULL)
+ return (int)GDB_HIDDENROUTEWPTCLASS;
+ else
+ return (int)GDB_DEFAULTWPTCLASS;
+}
+
+
#ifndef UTF8_SUPPORT
char *gdb_garmin_to_utf8(const char *s)
{
waypoint *wpt;
wpt = find_waypt_by_name(name);
- if (wpt != NULL) wpt = waypt_dupe(wpt);
+ if (wpt == NULL)
+ {
+ if (gdb_via != 0) return NULL;
+ wpt = gdb_find_wpt_q_by_name((queue *)&gdb_hidden->waypoint_list, name);
+ }
+ if (wpt != NULL)
+ wpt = waypt_dupe(wpt);
else
{
- gdb_find_wpt_q_by_name((queue *)&gdb_hidden->waypoint_list, name);
- if (wpt != NULL) wpt = waypt_dupe(wpt);
- else
- {
- wpt = waypt_new();
- wpt->shortname = xstrdup(name);
- wpt->latitude = lat;
- wpt->longitude = lon;
- wpt->altitude = alt;
- wpt->depth = unknown_alt;
- }
+ wpt = waypt_new();
+ wpt->shortname = xstrdup(name);
+ wpt->latitude = lat;
+ wpt->longitude = lon;
+ wpt->altitude = alt;
+ wpt->depth = unknown_alt;
}
return wpt;
}
-static size_t
-gdb_fread(void *target, size_t size, size_t count, FILE *fin)
+size_t
+gdb_fread(void *target, size_t size)
{
size_t result;
- result = fread(target, size, count, fin);
- if (result < count)
+ result = fread(target, 1, size, fin);
+ if (result < size)
{
if (feof(fin) != 0)
fatal(MYNAME ": unexpected end of file \"%s\"!\n", fin_name);
return result;
}
-static int
-gdb_fread_str(FILE *fin, char *dest, size_t maxlen)
+int
+gdb_fread_str(char *dest, size_t maxlen)
{
int c;
int res = 0;
fatal(MYNAME ": local buffer overflow detected, please report!\n");
}
-static int
-gdb_fread_le(FILE *fin, void *dest, size_t size, int bit_count, const char *field)
+int
+gdb_fread_le(void *dest, size_t size, int bit_count, const char *prefix, const char *field)
{
char buff[32];
unsigned char *c = dest;
double *db = dest;
if ((bit_count >> 3) != size)
- fatal(MYNAME ": internal error (gdb_le_read/%d/%d/%s)!\n", size, bit_count >> 3, field);
+ fatal(MYNAME "%s: Internal error (gdb_le_read/%d/%d/%s)!\n", prefix, (int)size, bit_count >> 3, field);
switch(bit_count)
{
case 8:
- gdb_fread(c, sizeof(*c), 1, fin);
- if (gdb_debug) printf(MYNAME ": gdb_fread_le : %d -> %s (0x%x))\n", *c, field, *c);
+ gdb_fread(c, sizeof(*c));
+ if (gdb_debug)
+ printf(MYNAME "%s: gdb_fread_le : %d -> %s (0x%x))\n", prefix, *c, field, *c);
return *c;
case 16:
if (sizeof(*sh) != size) fatal(MYNAME ": internal decl.!\n");
- gdb_fread(sh, sizeof(*sh), 1, fin);
+ gdb_fread(sh, sizeof(*sh));
*sh = le_read16(sh);
- if (gdb_debug) printf(MYNAME ": gdb_fread_le : %d -> %s (0x%x))\n", *sh, field, *sh);
+ if (gdb_debug)
+ printf(MYNAME "%s: gdb_fread_le : %d -> %s (0x%x))\n", prefix, *sh, field, *sh);
return *sh;
case 32:
- gdb_fread(li, 4, 1, fin);
+ gdb_fread(li, 4);
*li = le_read32(li);
- if (gdb_debug) printf(MYNAME ": gdb_fread_le : %d -> %s (0x%x)\n", *li, field, *li);
+ if (gdb_debug)
+ printf(MYNAME "%s: gdb_fread_le : %d -> %s (0x%x)\n", prefix, *li, field, *li);
return *li;
case 64:
- gdb_fread(buff, sizeof(*db), 1, fin);
+ gdb_fread(buff, sizeof(*db));
le_read64(db, buff);
- if (gdb_debug) printf(MYNAME ": gdb_fread_le : %g -> %s\n", *db, field);
+ if (gdb_debug)
+ printf(MYNAME "%s: gdb_fread_le : %g -> %s\n", prefix, *db, field);
return 0;
default:
- fatal(MYNAME ": unsupported bit count (%d) in gdb_le_read!\n", bit_count);
+ fatal(MYNAME "%s: unsupported bit count (%d) in gdb_le_read!\n", prefix, bit_count);
}
}
-static void
-gdb_is_valid(int is, const char *comment)
+int
+gdb_fread_flag(const char value) /* read one byte and compare to value */
{
- if (is == 0) fatal(MYNAME ": error in database structure (%s)!\n", comment);
+ char c;
+
+ gdb_fread(&c, 1);
+ return (c == value);
}
-static void
+void
+gdb_is_valid(int is, const char *prefix, const char *comment)
+{
+ if (is == 0)
+ {
+ printf(MYNAME ": Reading database \"%s\"\n", fin_name);
+ fatal(MYNAME "-%s: Found error in data (%s)!\n", prefix, comment);
+ }
+}
+
+void
+gdb_is_validf(int is, const char *prefix, const char *format, ...)
+{
+ va_list args;
+ char buff[256];
+
+ if (is != 0) return;
+
+ va_start(args, format);
+ if (fin_name != NULL)
+ printf(MYNAME "-%s: Reading from database \"%s\"\n", prefix, fin_name);
+ else
+ printf(MYNAME "-%s: Writing to database \"%s\"\n", prefix, fout_name);
+ printf(MYNAME "-%s: ");
+ vprintf(format, args);
+ puts("");
+
+ va_end(args);
+ fatal("");
+}
+
+/********************************************************************************************************/
+/* %%% read file header */
+/********************************************************************************************************/
+
+void
gdb_read_file_header(void)
{
char buff[128];
int i, reclen;
+ const char *prefix = "read_head";
/*
We starts with standard binary read.
A gdb_fread_str works too, but if we get a wrong file as input,
*/
if (6 != fread(buff, 1, 6, fin))
- fatal(MYNAME ": invalid file \"%s\"!\n", fin_name);
+ fatal(MYNAME ": Invalid file \"%s\"!\n", fin_name);
if (strcmp(buff, "MsRcf") != 0)
- fatal(MYNAME ": invalid file \"%s\"!\n", fin_name);
+ fatal(MYNAME ": Invalid file \"%s\"!\n", fin_name);
- gdb_fread(&reclen, 4, 1, fin);
+ gdb_fread(&reclen, 4);
reclen = le_read32(&reclen);
- gdb_is_valid(reclen == gdb_fread_str(fin, buff, sizeof(buff)), "header");
-
- gdb_is_valid(buff[0] == 'D', "header");
+ gdb_is_valid(reclen == gdb_fread_str(buff, sizeof(buff)), prefix, "Invalid record length");
+ if (buff[0] != 'D')
+ fatal(MYNAME ": Invalid file \"%s\"!\n", fin_name);
+
switch(buff[1])
{
case 'k':
gdb_ver = 2;
break;
default:
- fatal(MYNAME ": non supported gdb version!\n");
+ fatal(MYNAME ": Non supported GDB version!\n");
}
if (global_opts.verbose_status > 0)
- printf(MYNAME ": found Garmin GPS Database version %d\n", gdb_ver);
+ printf(MYNAME ": Found Garmin GPS Database version %d.0\n", gdb_ver);
- gdb_fread(&reclen, 4, 1, fin);
+ gdb_fread(&reclen, 4);
reclen = le_read32(&reclen);
- gdb_is_valid(reclen < sizeof(buff), "header");
- gdb_fread(buff, reclen, 1, fin);
+ gdb_is_valid(reclen < sizeof(buff), prefix, "Invalid record length");
+ gdb_fread(buff, reclen);
- gdb_is_valid(0 == gdb_fread_str(fin, buff, sizeof(buff)), "header");
+ gdb_is_valid(0 == gdb_fread_str(buff, sizeof(buff)), prefix, "header");
- i = gdb_fread_str(fin, buff, sizeof(buff));
- gdb_is_valid((i == 9) && (strcmp(buff, "MapSource") == 0), "header");
+ i = gdb_fread_str(buff, sizeof(buff));
+ gdb_is_valid((i == 9) && (strcmp(buff, "MapSource") == 0), prefix, "MapSource magic");
}
+/********************************************************************************************************/
+/* %%% read waypoint */
+/********************************************************************************************************/
+
waypoint *
gdb_read_wpt(const size_t fileofs, int *wptclass)
{
- char xname[MPSNAMEBUFFERLEN];
- char xdesc[MPSDESCBUFFERLEN];
- char xnotes[MPSNOTESBUFFERLEN];
+ char xname[GDB_NAME_BUFFERLEN];
+ char xdesc[GDB_DESCR_BUFFERLEN];
+ char xnotes[GDB_NOTES_BUFFERLEN];
int xclass;
int xlat, xlon, xdisplay, xcolour, xicon, xtime;
short xcat;
double xdepth = unknown_alt;
double xalt = unknown_alt;
+ double xproximity = unknown_alt;
waypoint *res;
-
- char *ctmp;
char buff[128];
-
size_t pos, delta;
+
+ const char *prefix = "wpt_read";
/********************************************************************************************************/
*/
/********************************************************************************************************/
- gdb_is_valid(gdb_fread_str(fin, xname, sizeof(xname)) > 0, "new waypoint");
+ gdb_is_valid(gdb_fread_str(xname, sizeof(xname)) > 0, prefix, "new waypoint");
gdb_convert_name_buff(xname, sizeof(xname));
- gdb_fread_le(fin, &xclass, sizeof(xclass), 32, "xclass");
- gdb_fread_str(fin, buff, sizeof(buff)); /* country */
+ gdb_fread_le(&xclass, sizeof(xclass), 32, prefix, "class");
+ gdb_fread_str(buff, sizeof(buff)); /* country */
- gdb_fread(buff, 22, 1, fin);
- xlat = gdb_fread_le(fin, &xlat, sizeof(xlat), 32, "xlat"); /* latitude */
- xlon = gdb_fread_le(fin, &xlon, sizeof(xlon), 32, "xlon"); /* latitude */
+ gdb_fread(buff, 22);
+ xlat = gdb_fread_le(&xlat, sizeof(xlat), 32, prefix, "latitude");
+ xlon = gdb_fread_le(&xlon, sizeof(xlon), 32, prefix, "longitude");
- gdb_fread(buff, 1, 1, fin);
- if (buff[0] == 1) /* altitude flag */
- {
- gdb_fread_le(fin, &xalt, sizeof(xalt), 64, "xalt"); /* altitude */
- }
+ if (gdb_fread_flag(1)) /* altitude flag */
+ gdb_fread_le(&xalt, sizeof(xalt), 64, prefix, "altitude");
- gdb_fread_str(fin, xdesc, sizeof(xdesc));
+ gdb_fread_str(xdesc, sizeof(xdesc)); /* description */
gdb_convert_name_buff(xdesc, sizeof(xdesc));
- gdb_fread(buff, 1, 1, fin); /* proximity flag */
- if (buff[0] == 1)
- {
- gdb_fread(buff, 8, 1, fin); /* proximity */
- }
+ if (gdb_fread_flag(1)) /* proximity flag */
+ gdb_fread_le(&xproximity, sizeof(xproximity), 64, prefix, "proximity");
- xdisplay = gdb_fread_le(fin, &xdisplay, sizeof(xdisplay), 32, "xdisplay");
- xcolour = gdb_fread_le(fin, &xcolour, sizeof(xcolour), 32, "xcolour");
- xicon = gdb_fread_le(fin, &xicon, sizeof(xicon), 32, "xicon");
+ xdisplay = gdb_fread_le(&xdisplay, sizeof(xdisplay), 32, prefix, "display");
+ xcolour = gdb_fread_le(&xcolour, sizeof(xcolour), 32, prefix, "colour");
+ xicon = gdb_fread_le(&xicon, sizeof(xicon), 32, prefix, "icon");
- /* ToDo: convert the icon !!! */
-
- gdb_fread_str(fin, buff, sizeof(buff)); /* city */
- gdb_fread_str(fin, buff, sizeof(buff)); /* state */
- gdb_fread_str(fin, buff, sizeof(buff)); /* facility */
- gdb_fread(buff, 1, 1, fin); /* unknown */
+ gdb_fread_str(buff, sizeof(buff)); /* city */
+ gdb_fread_str(buff, sizeof(buff)); /* state */
+ gdb_fread_str(buff, sizeof(buff)); /* facility */
- gdb_fread(buff, 1, 1, fin); /* depth flag */
- if (buff[0] == 1)
- {
- gdb_fread_le(fin, &xdepth, sizeof(xdepth), 64, "xdepth"); /* depth */
- }
+ gdb_fread(buff, 1); /* unknown */
- gdb_fread(buff, 1, 1, fin);
- gdb_fread(buff, 1, 1, fin);
- gdb_fread(buff, 1, 1, fin);
+ if (gdb_fread_flag(1)) /* depth flag */
+ gdb_fread_le(&xdepth, sizeof(xdepth), 64, prefix, "depth");
- if (buff[0] != 0)
- gdb_fread(buff, 3, 1, fin);
+ gdb_fread(buff, 1);
+ gdb_fread(buff, 1);
+
+ if (gdb_fread_flag(0))
+ gdb_fread(buff, 4);
else
- gdb_fread(buff, 4, 1, fin);
+ gdb_fread(buff, 3);
- gdb_fread_str(fin, xnotes, sizeof(xnotes));
+ gdb_fread_str(xnotes, sizeof(xnotes));
gdb_convert_name_buff(xnotes, sizeof(xnotes));
- xcat = gdb_fread_le(fin, &xcat, sizeof(xcat), 16, "xcat");
+ xcat = gdb_fread_le(&xcat, sizeof(xcat), 16, prefix, "category");
- gdb_fread(buff, 1, 1, fin); /* temperature flag */
- if (buff[0] == 1)
- {
- gdb_fread(buff, 8, 1, fin); /* temperature */
- }
+ if (gdb_fread_flag(1)) /* temperature flag */
+ gdb_fread(buff, 8); /* temperature */
/* Here comes 1 .. 6 unknown bytes
!!! 6 only if class > 0 !!!
pos = ftell(fin);
delta = fileofs - pos;
- gdb_is_valid(delta > 0, "waypoint final");
+ gdb_is_valid(delta > 0, prefix, "waypoint final");
if ((delta & 1) == 0)
{
- gdb_fread(buff, 1, 1, fin);
+ gdb_fread(buff, 1);
delta--;
}
xtime = 0;
- gdb_fread(buff, 1, 1, fin);
- if (buff[0] == 1)
+ if (gdb_fread_flag(1))
{
- gdb_is_valid(delta==5, "??? waypoint time ???");
- gdb_fread_le(fin, &xtime, sizeof(xtime), 32, "xtime");
+ gdb_is_valid(delta==5, prefix, "Waypoint time");
+ gdb_fread_le(&xtime, sizeof(xtime), 32, prefix, "time");
}
else
- gdb_is_valid(delta==1, "no waypoint time");
+ gdb_is_valid(delta==1, prefix, "No waypoint time");
*wptclass = xclass;
res->latitude = GPS_Math_Semi_To_Deg(xlat);
res->longitude = GPS_Math_Semi_To_Deg(xlon);
res->altitude = xalt;
+ res->depth = xdepth;
+ res->proximity = xproximity;
res->creation_time = xtime;
+#if 0
+ res->garmin_data = xcalloc(1, sizeof(garmin_data_t));
+ res->garmin_data->colour = xcolour;
+ res->garmin_data->category = xcat;
+ res->garmin_data->display = xdisplay;
+#endif
/* might need to change this to handle version dependent icon handling */
res->icon_descr = gdb_find_desc_from_icon_number(xicon, MAPSOURCE);
-
- gdb_is_valid(fabs(res->latitude) <= 90.0 && fabs(res->longitude) <= 180.0, " - wpt read: invalid lat or lon");
+
+ gdb_is_validf(fabs(res->latitude) <= 90.0, prefix, "%s has invalid latitude (%f)",
+ res->shortname, res->latitude);
return res;
}
+/********************************************************************************************************/
+/* %%% read route */
+/********************************************************************************************************/
+
route_head *
gdb_read_route(void)
{
- char xname[MPSNAMEBUFFERLEN];
- char xwptname[MPSNAMEBUFFERLEN];
+ char xname[GDB_NAME_BUFFERLEN];
+ char xwptname[GDB_NAME_BUFFERLEN];
int xclass;
double xalt;
- double xlat, xlon;
+ double xlat = 0; /* compiler warnings */
+ double xlon = 0; /* compiler warnings */
char buff[256];
- int count;
- int checked;
+ int count, origin;
int isteps, ilink;
int semilat, semilon;
+ int maxlat, maxlon, minlon, minlat;
+ char auto_name;
route_head *route;
waypoint *wpt;
- int i, j;
- size_t curpos;
+ const char *prefix = "rte_read_head";
+ const char *prefix1 = "rte_read_loop";
+ const char *prefix2 = "rte_ils_loop";
+ const char *prefix3 = "rte_read_final";
- gdb_is_valid(gdb_fread_str(fin, xname, sizeof(xname)) > 0, "route start");
+ gdb_is_valid(gdb_fread_str(xname, sizeof(xname)) > 0, prefix, "Route has no name");
gdb_convert_name_buff(xname, sizeof(xname));
-
- gdb_fread_le(fin, buff, 2, 16, "auto_name");
- gdb_fread_le(fin, buff, 4, 32, "max_lat");
- gdb_fread_le(fin, buff, 4, 32, "max_lon");
- gdb_fread(buff, 1, 1, fin);
- if (buff[0] == 1) gdb_fread_le(fin, buff, 8, 64, "max_alt");
+ gdb_fread_le(&auto_name, sizeof(auto_name), 8, prefix, "auto name");
+ if (gdb_fread_flag(0)) /* max. data flag */
+ {
+ gdb_fread_le(buff, 4, 32, prefix, "max. latitude");
+ gdb_fread_le(buff, 4, 32, prefix, "max. longitude");
+
+ gdb_fread(buff, 1);
+ if (buff[0] == 1) gdb_fread_le(buff, 8, 64, prefix, "max. altitude");
- gdb_fread_le(fin, buff, 4, 32, "min_lat");
- gdb_fread_le(fin, buff, 4, 32, "min_lon");
+ gdb_fread_le(buff, 4, 32, prefix, "min. latitude");
+ gdb_fread_le(buff, 4, 32, prefix, "min. longitude");
- gdb_fread(buff, 1, 1, fin);
- if (buff[0] == 1) gdb_fread_le(fin, buff, 8, 64, "min_alt");
+ gdb_fread(buff, 1);
+ if (buff[0] == 1)
+ gdb_fread_le(buff, 8, 64, prefix, "min. altitude");
+ }
- gdb_fread_le(fin, &count, sizeof(count), 32, "rte_count");
- if (count <= 0) return NULL;
+ gdb_fread_le(&count, sizeof(count), 32, prefix, "count");
+
+ if (count == 0)
+ fatal(MYNAME "%s: !!! Empty routes are not allowed !!!\n", prefix);
route = route_head_alloc();
route->rte_name = xstrdup(xname);
route_add_head(route);
-#if GDB_DEBUG
- printf(MYNAME " - route: \"%s\" with %d point(s)\n", route->rte_name, count);
+#ifdef GDB_DEBUG
+ printf(MYNAME " - route: \"%s\" with %d point(s)\n", xname, count);
#endif
-
- if (count <= 0) return route;
-
- count--;
+ origin = count;
while (count--)
{
- gdb_fread_str(fin, xwptname, sizeof(xwptname)); /* name */
+ gdb_fread_str(xwptname, sizeof(xwptname)); /* waypoint name */
gdb_convert_name_buff(xwptname, sizeof(xwptname));
+
+ gdb_fread_le(&xclass, sizeof(xclass), 32, prefix1, "class"); /* class */
+ gdb_fread_str(buff, sizeof(buff)); /* country */
- gdb_fread_le(fin, &xclass, sizeof(xclass), 32, "xclass"); /* class */
- gdb_fread_str(fin, buff, sizeof(buff)); /* country */
-
- gdb_fread(buff, 22, 1, fin); /* sub class data */
- i = 0;
- while (i < sizeof(buff))
- {
- gdb_fread(&buff[i], 1, 1, fin);
- if (buff[i] == 0) break;
- i++;
- }
+ gdb_fread(buff, 22); /* sub class data */
+ gdb_fread(buff, 1);
+ gdb_is_valid(buff[0] == 0, prefix1, "Should by zero byte (1)");
/* The next thing is the unknown 0x03 0x00 .. 0x00 (18 bytes) */
- gdb_fread(buff, 18, 1, fin);
-
- gdb_fread_le(fin, &isteps, sizeof(isteps), 32, "isteps");
+ /* OK: this should be, but i've seen exceptions (...cannot verify the first byte */
+ gdb_fread(buff, 18);
+
+ gdb_fread_le(&isteps, sizeof(isteps), 32, prefix1, "interlink steps");
- if (isteps <= 0) return route;
+ if (isteps <= 0) /* ??? end of route or error ??? */
+ {
+ gdb_is_valid(count == 0, prefix3, "Zero interlink steps within route");
+
+ gdb_fread(buff, 1);
+ gdb_is_valid((buff[0] == 1), prefix3, "last seq.(1)");
+
+ if (gdb_ver > 1)
+ gdb_fread(buff, 8); /* Unknown 8 bytes since gdb v2 */
+
+ gdb_fread(buff, 1);
+ gdb_is_valid((buff[0] == 0), prefix3, "last seq.(2)");
+
+ wpt = gdb_create_rte_wpt(xwptname, xlat, xlon, xalt);
+ if (wpt != NULL)
+ route_add_wpt(route, wpt);
+ return route;
+ }
- gdb_fread_le(fin, &semilat, sizeof(semilat), 32, "semilat");
- gdb_fread_le(fin, &semilon, sizeof(semilon), 32, "semilon");
+ gdb_fread_le(&semilat, sizeof(semilat), 32, prefix1, "semi-latitude");
+ gdb_fread_le(&semilon, sizeof(semilon), 32, prefix1, "semi-longitude");
xlat = GPS_Math_Semi_To_Deg(semilat);
xlon = GPS_Math_Semi_To_Deg(semilon);
- gdb_is_valid(fabs(xlat) <= 90.0 && fabs(xlon) <= 180.0, " - rte: read loop: invalid lat or lon");
+ gdb_is_validf(fabs(xlat) <= 90.0, prefix1, "Invalid latitude (%f)", xlat);
- xalt = unknown_alt;
- gdb_fread(buff, 1, 1, fin); /* altitude flag */
- if (buff[0] == 1)
- {
- gdb_fread_le(fin, &xalt, sizeof(xalt), 64, "xalt");
- }
+ if (gdb_fread_flag(1)) /* altitude flag */
+ gdb_fread_le(&xalt, sizeof(xalt), 64, prefix1, "altitude");
+ else
+ xalt = unknown_alt;
wpt = gdb_create_rte_wpt(xwptname, xlat, xlon, xalt);
- route_add_wpt(route, wpt);
+ if (wpt != NULL)
+ route_add_wpt(route, wpt);
- for (ilink = isteps-1; ilink > 0; ilink--)
+ while (--isteps > 0)
{
- gdb_fread_le(fin, &semilat, sizeof(semilat), 32, "semilat");
- gdb_fread_le(fin, &semilon, sizeof(semilon), 32, "semilon");
- gdb_fread(buff, 1, 1, fin); /* altitude flag */
- if (buff[0] == 1) gdb_fread_le(fin, &xalt, sizeof(xalt), 64, "xalt");
+ gdb_fread_le(&semilat, sizeof(semilat), 32, prefix2, "semi-latitude");
+ gdb_fread_le(&semilon, sizeof(semilon), 32, prefix2, "semi-longitude");
+ gdb_fread(buff, 1); /* altitude flag */
+ if (buff[0] == 1)
+ gdb_fread_le(&xalt, sizeof(xalt), 64, prefix2, "altitude");
+
xlat = GPS_Math_Semi_To_Deg(semilat);
xlon = GPS_Math_Semi_To_Deg(semilon);
- gdb_is_valid(fabs(xlat) <= 90.0 && fabs(xlon) <= 180.0, " - rte/ils: read loop: invalid lat or lon");
+ gdb_is_validf(fabs(xlat) <= 90.0, prefix2, "Invalid latitude (%f)", xlat);
}
- gdb_fread(buff, 1, 1, fin); /* NULL */
- gdb_is_valid(buff[0] == 0, "should be zero byte");
-
- gdb_fread(buff, 4, 1, fin); /* link max lat */
- gdb_fread(buff, 4, 1, fin); /* link max lon */
- gdb_fread(buff, 1, 1, fin);
- if (buff[0] == 1)
- {
- gdb_fread(buff, 8, 1, fin); /* link max alt validity + alt */
- }
- gdb_fread(buff, 4, 1, fin); /* link min lat */
- gdb_fread(buff, 4, 1, fin); /* link min lon */
+ gdb_fread(buff, 1);
+ gdb_is_valid(buff[0] == 0, prefix1, "\"Zero\" byte expected");
- gdb_fread(buff, 1, 1, fin);
- if (buff[0] == 1)
- {
- gdb_fread(buff, 8, 1, fin); /* link min alt validity + alt */
- }
+ gdb_fread_le(&maxlat, sizeof(maxlat), 32, prefix1, "max. latitude");
+ gdb_fread_le(&maxlon, sizeof(maxlon), 32, prefix1, "max. longitude");
- /* find the end of the record */
+ if (gdb_fread_flag(1)) /* link max alt validity + alt */
+ gdb_fread(buff, 8);
- curpos = ftell(fin);
-
- /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- the stuff here is very tricky and did not base on any
- any knowledgement, but seems to work.
- The final structure varied from file to file and i
- could not find any connection with data, gdb version
- and any unknown bytes and bits. Hmm.
- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+ gdb_fread_le(&minlat, sizeof(minlat), 32, prefix1, "min. latitude");
+ gdb_fread_le(&minlon, sizeof(minlon), 32, prefix1, "min. longitude");
- memset(buff, 0, sizeof(buff));
- checked = 0;
-
- j = 18;
- while (checked == 0 && j-- > 0)
- {
- for (i=1; i<8; i++) buff[i-1] = buff[i];
- gdb_fread(&buff[7], 1, 1, fin);
- for (i=0; i<8; i++)
- {
- if (buff[i] != -1) break;
- if (i == 7) checked = 1;
- }
+ if (gdb_fread_flag(1)) /* link min alt validity + alt */
+ gdb_fread(buff, 2 * sizeof(int));
- }
- if (checked == 0)
- {
- fseek(fin, curpos, SEEK_SET);
- }
- else
- {
- while (1)
- {
- gdb_fread(buff, 1, 1, fin);
- if (buff[0] != -1)
- {
- fseek(fin, ftell(fin)-1, SEEK_SET);
- break;
- }
- }
-
- }
+ if (gdb_ver > 1)
+ gdb_fread(buff, 8); /* unknown 8 bytes since gdb v2 */
}
- gdb_fread_str(fin, xwptname, sizeof(xwptname)); /* name */
- gdb_convert_name_buff(xwptname, sizeof(xwptname));
-
-#if GDB_DEBUG
- printf(MYNAME " - rte/fin: \"%s\"\n", xwptname);
-#endif
- gdb_fread_le(fin, &xclass, sizeof(xclass), 32, "xclass"); /* class */
- gdb_fread_str(fin, buff, sizeof(buff)); /* country */
-
- wpt = gdb_create_rte_wpt(xwptname, xlat, xlon, xalt);
- route_add_wpt(route, wpt);
+ /* This should normally never happen; end of route is handled in main loop before this */
- return route;
+ fatal(MYNAME "-%s: Unexpected end of route \"%s\"!", prefix1, xname);
}
route_head *
gdb_read_track(const size_t max_file_pos)
{
- char xname[MPSNAMEBUFFERLEN];
+ char xname[GDB_NAME_BUFFERLEN];
unsigned char xdisplay;
int xcolour;
int xlat;
route_head *track;
waypoint *wpt;
- gdb_fread_str(fin, xname, sizeof(xname));
+ const char *prefix0 = "trk_read";
+ const char *prefix = "trk_read_loop";
+
+ gdb_fread_str(xname, sizeof(xname));
gdb_convert_name_buff(xname, sizeof(xname));
- gdb_fread_le(fin, &xdisplay, sizeof(xdisplay), 8, "xdisplay");
- gdb_fread_le(fin, &xcolour, sizeof(xcolour), 32, "xcolour");
- gdb_fread_le(fin, &count, sizeof(count), 32, "count");
+ gdb_fread_le(&xdisplay, sizeof(xdisplay), 8, prefix0, "display");
+ gdb_fread_le(&xcolour, sizeof(xcolour), 32, prefix0, "colour");
+ gdb_fread_le(&count, sizeof(count), 32, prefix0, "count");
track = route_head_alloc();
track->rte_name = xstrdup(xname);
track_add_head(track);
- while (count > 0)
+ while (count--)
{
- count--;
-
- gdb_fread_le(fin, &xlat, sizeof(xlat), 32, "xlat");
- gdb_fread_le(fin, &xlon, sizeof(xlon), 32, "xlon");
+ gdb_fread_le(&xlat, sizeof(xlat), 32, prefix, "latitude");
+ gdb_fread_le(&xlon, sizeof(xlon), 32, prefix, "longitude");
- gdb_fread(buff, 1, 1, fin); /* altitude flag */
+ gdb_fread(buff, 1); /* altitude flag */
if (buff[0] == 1)
- gdb_fread_le(fin, &xalt, sizeof(xalt), 64, "xalt");
+ gdb_fread_le(&xalt, sizeof(xalt), 64, prefix, "altitude");
- gdb_fread(buff, 1, 1, fin); /* date/time flag */
+ gdb_fread(buff, 1); /* date/time flag */
if (buff[0] == 1)
- gdb_fread_le(fin, &xtime, sizeof(xtime), 32, "xtime");
+ gdb_fread_le(&xtime, sizeof(xtime), 32, prefix, "time");
- gdb_fread(buff, 1, 1, fin); /* depth flag */
+ gdb_fread(buff, 1); /* depth flag */
if (buff[0] == 1)
- gdb_fread_le(fin, &xdepth, sizeof(xdepth), 64, "xdepth");
+ gdb_fread_le(&xdepth, sizeof(xdepth), 64, prefix, "depth");
- gdb_fread(buff, 1, 1, fin);
+ gdb_fread(buff, 1); /* temperature flag */
if (buff[0] == 1)
- gdb_fread_le(fin, &xtemp, sizeof(xtemp), 64, "xtemp");
+ gdb_fread_le(&xtemp, sizeof(xtemp), 64, prefix, "temperature");
wpt = waypt_new();
wpt->altitude = xalt;
wpt->depth = xdepth;
- gdb_is_valid(fabs(wpt->latitude) <= 90.0 && fabs(wpt->longitude) <= 180.0, " - trk read loop: invalid lat or lon");
+ gdb_is_validf(fabs(wpt->latitude) <= 90.0, prefix, "Invalid latitude (%f)", wpt->latitude);
route_add_wpt(track, wpt);
}
+ gdb_fread(buff, 1);
+
return track;
}
+/*******************************************************************************/
-static void
+void
gdb_read_data(void)
{
- int reclen, done;
+ int reclen, warnings;
char typ;
- size_t curpos, deltapos;
- waypoint *wpt;
+ size_t curpos, anchor;
int wptclass;
- done = 0;
- while (!feof(fin) && (done == 0))
- {
+ const char *prefix = "main_read_loop";
+
+ gdb_hidden = route_head_alloc();
+ track_add_head(gdb_hidden);
+
+ warnings = 0;
+
+ anchor = ftell(fin);
- gdb_fread_le(fin, &reclen, sizeof(reclen), 32, "reclen");
- gdb_is_valid(reclen > 0 && reclen < 0x1F00000, "gdb data loop");
- gdb_fread(&typ, 1, 1, fin);
+ /* we go twice through the file to keep sure, all waypoints
+ are loaded before any route has to be handled */
+
+ while (feof(fin) == 0)
+ {
+
+ gdb_fread_le(&reclen, sizeof(reclen), 32, prefix, "record length");
+ gdb_is_valid(reclen > 0 && reclen < 0x1F00000, prefix, "record length");
+ gdb_fread(&typ, 1);
curpos = ftell(fin);
- switch(typ)
+ if (typ == 'W')
{
- case 'W':
- wpt = gdb_read_wpt(curpos + reclen, &wptclass);
- if (wpt != NULL )
+ int delta;
+ waypoint *wpt;
+
+ wpt = gdb_read_wpt(curpos + reclen, &wptclass);
+ if (wpt != NULL )
+ {
+ if (wptclass == 0)
+ waypt_add(wpt);
+ else if (gdb_via == 0)
+ route_add_wpt(gdb_hidden, wpt);
+ else
+ waypt_free(wpt);
+ }
+ delta = (int)((curpos + reclen) - ftell(fin));
+ if (delta != 0)
+ {
+ if ((warnings & 1) == 0)
{
- if (wptclass == 0)
- waypt_add(wpt);
- else
- route_add_wpt(gdb_hidden, wpt);
+ warnings |= 1;
+ warning(MYNAME "-%s: At least one incomplete waypoint read (%d byte(s) left).\n", prefix, delta);
}
- deltapos = (curpos+reclen)-ftell(fin);
- break;
- case 'T':
- gdb_read_track(curpos + reclen);
- break;
- case 'R':
- gdb_read_route();
- break;
- case 'L':
- break;
- case 'V':
- done = 1;
- break;
- default:
- printf(MYNAME ": found unknown record type \"%c\"!\n", typ);
+ fseek(fin, curpos + reclen, SEEK_SET);
+ }
+ continue;
}
+ else if (typ == 'V')
+ break;
+
fseek(fin, curpos + reclen, SEEK_SET);
}
+
+ clearerr(fin);
+ fseek(fin, anchor, SEEK_SET);
+
+ while (feof(fin) == 0)
+ {
+ gdb_fread_le(&reclen, sizeof(reclen), 32, prefix, "record length");
+ gdb_is_valid(reclen > 0 && reclen < 0x1F00000, prefix, "record length");
+ gdb_fread(&typ, 1);
+
+ curpos = ftell(fin);
+
+ if ((typ == 'R') || (typ == 'T'))
+ {
+ int flag, delta;
+
+ if (typ == 'R')
+ {
+ gdb_read_route();
+ flag = 2;
+ }
+ else
+ {
+ gdb_read_track(curpos + reclen);
+ flag = 4;
+ }
+ delta = (int)((curpos + reclen) - ftell(fin));
+ if (delta != 0)
+ {
+ if ((delta != reclen) && ((warnings & flag) == 0))
+ {
+ warnings |= flag;
+ warning(MYNAME "-%s: At least one incomplete %s (gdb v%d.0, %d byte(s) left).\n",
+ prefix, (typ == 'R') ? "route" : "track", gdb_ver, delta);
+ }
+ fseek(fin, curpos + reclen, SEEK_SET);
+ }
+ }
+ else
+ {
+ if (typ == 'V') break;
+
+ switch(typ)
+ {
+ case 'D': break;
+ case 'L': break;
+ case 'W': break;
+ default: warning(MYNAME "-%s: Found unknown record type \"%c\"!\n", prefix, typ);
+ }
+ fseek(fin, curpos + reclen, SEEK_SET);
+ }
+ }
+
+ /* finally kill our temporary queue */
+ track_del_head(gdb_hidden);
+}
+
+/*******************************************************************************/
+/* %%% write support %%% */
+/*******************************************************************************/
+
+/* helpers */
+
+waypoint **
+gdb_route_point_list(const route_head *route, int *count)
+{
+ waypoint **result;
+ queue *elem, *tmp;
+ int i = 0;
+
+ QUEUE_FOR_EACH((queue *)&route->waypoint_list, elem, tmp)
+ {
+ waypoint *wpt = (waypoint *)elem;
+ if ((gdb_via == 0) ||
+ (gdb_detect_rtept_class(wpt) == GDB_DEFAULTWPTCLASS)) i++;
+ }
+
+ *count = i;
+ if (i == 0) return NULL;
+
+ result = xcalloc(i, sizeof(*result));
+
+ i = 0;
+ QUEUE_FOR_EACH((queue *)&route->waypoint_list, elem, tmp)
+ {
+ waypoint *wpt = (waypoint *)elem;
+ if ((gdb_via == 0) ||
+ (gdb_detect_rtept_class(wpt) == GDB_DEFAULTWPTCLASS))
+ result[i++] = wpt;
+ }
+
+ return result;
+}
+
+void
+gdb_fwrite(const void *data, const size_t size)
+{
+ fwrite(data, size, 1, fout);
+}
+
+void
+gdb_fwrite_str(const char *str, const int len)
+{
+
+ if (len >= 0)
+ gdb_fwrite(str, len); /* write a string with fixed length */
+ else
+ {
+ char *tmp = str_utf8_to_cp1252((str != NULL) ? str : "");
+ gdb_fwrite(tmp, strlen(tmp) + 1);
+ xfree(tmp);
+ }
+}
+
+void
+gdb_fwrite_le(const void *data, const size_t size)
+{
+ int i;
+ short s;
+ char buff[8];
+
+ switch(size)
+ {
+ case 1:
+ gdb_fwrite(data, 1);
+ break;
+
+ case 2: /* sizeof(short): */
+ s = *(short *)data;
+ le_write16(&s, s);
+ gdb_fwrite(&s, 2);
+ break;
+
+ case 4: /* sizeof(int): */
+ i = *(int *)data;
+ le_write32(&i, i);
+ gdb_fwrite(&i, 4);
+ break;
+
+ case 8: /* sizeof(double): */
+ le_read64(buff, data);
+ gdb_fwrite(buff, 8);
+ break;
+
+ default:
+ fatal(MYNAME "-write_le: Unsupported data size (%ld)!\n", size);
+ }
+}
+
+void
+gdb_fwrite_alt(const double alt, const double unknown_value)
+{
+ char c0 = 0;
+ char c1 = 1;
+
+ if (alt != unknown_value) /* proximity / depth / altitude */
+ {
+ gdb_fwrite(&c1, 1);
+ gdb_fwrite_le(&alt, sizeof(alt));
+ }
+ else
+ gdb_fwrite(&c0, 1); /* no value */
+}
+
+void
+gdb_fwrite_int(const int data)
+{
+ gdb_fwrite_le(&data, sizeof(data));
+}
+
+void
+gdb_fwrite_icon(const waypoint *wpt) /* partly taken from mapsource.c */
+{
+ int icon;
+ char buff[128];
+
+ if ( /* handle custom icons, which are linked to -2 in garmin_tables.c */
+ (wpt->icon_descr != NULL) &&
+ (sscanf(wpt->icon_descr, "%s%d", buff, &icon) == 2) &&
+ (case_ignore_strcmp(buff, "Custom") == 0) &&
+ (icon >= 0) && (icon <= 63)
+ )
+ {
+ icon += 500;
+ }
+ else
+ {
+ /* might need to change this to handle version dependent icon handling */
+ icon = gdb_find_icon_number_from_desc(wpt->icon_descr, MAPSOURCE);
+ if (get_cache_icon(wpt) /* && wpt->icon_descr && (strcmp(wpt->icon_descr, "Geocache Found") != 0)*/)
+ {
+ icon = gdb_find_icon_number_from_desc(get_cache_icon(wpt), MAPSOURCE);
+ }
+ }
+ gdb_fwrite_le(&icon, sizeof(icon));
+}
+
+/*******************************************************************************/
+/* %%% write file header %%% */
+/*-----------------------------------------------------------------------------*/
+
+void
+gdb_write_file_header(const struct tm *tm)
+{
+ char buff[128];
+ char *c;
+ int len;
+
+ gdb_fwrite_str("MsRcf", -1);
+ gdb_fwrite_int(2);
+
+ strncpy(buff, "Dx", sizeof(buff));
+ buff[1] = 'k' - 1 + gdb_ver;
+ gdb_fwrite_str(buff, -1);
+
+#if 0
+ strncpy(buff, "A].SQA*Dec 27 2004*17:40:51", sizeof(buff)); /* MapSource V6.5 */
+#else
+ /* This is our "Watermark" to show this file was not created by MapSource */
+ /* !!! We should define the date use through Makefile !!! */
+ strncpy(buff, "A].GPSBabel*Jul 29 2005*09:52:51", sizeof(buff)); /* gpsbabel V1.2.6 */
+#endif
+ len = strlen(buff);
+ buff[2] = 2;
+
+ c = buff;
+ while ((c = strchr(c, '*'))) *c++ = '\0';
+
+ gdb_fwrite_int(len);
+ gdb_fwrite_str(buff, len + 1);
+
+ gdb_fwrite_str("MapSource", -1); /* MapSource magic */
+}
+
+/*******************************************************************************/
+/* %%% write waypoints %%% */
+/*-----------------------------------------------------------------------------*/
+
+void
+gdb_write_waypt(const waypoint *wpt, const int hidden)
+{
+ int i;
+ char ffbuf[32], zbuf[32];
+ char c0 = 0;
+ char c1 = 1;
+
+ gdb_is_validf((fabs(wpt->latitude) <= 90), "wpt_write",
+ "%s: Invalid latitude (%f) detected\n", wpt->shortname, wpt->latitude);
+
+ memset(ffbuf, 0xFF, sizeof(ffbuf));
+ memset(zbuf, 0x00, sizeof(zbuf));
+
+ gdb_fwrite_str(wpt->shortname, -1);
+
+ gdb_fwrite_int( (hidden != 0) ?
+ GDB_HIDDENROUTEWPTCLASS : GDB_DEFAULTWPTCLASS); /* class */
+ gdb_fwrite_str("", -1); /* country */
+
+ gdb_fwrite(zbuf, 4); /* subclass part 1 */
+ gdb_fwrite(ffbuf, 12); /* subclass part 2 */
+ gdb_fwrite(zbuf, 2); /* subclass part 3 */
+ gdb_fwrite(ffbuf, 4); /* unknown */
+
+ gdb_fwrite_int(GPS_Math_Deg_To_Semi(wpt->latitude));
+ gdb_fwrite_int(GPS_Math_Deg_To_Semi(wpt->longitude));
+
+ gdb_fwrite_alt(wpt->altitude, unknown_alt); /* altitude */
+ gdb_fwrite_str(wpt->description, -1); /* description */
+ gdb_fwrite_alt(wpt->proximity, unknown_alt); /* proximity */
+
+#if 0
+ gdb_fwrite_int((wpt->garmin_data != NULL) ? wpt->garmin_data->display : 0); /* display */
+ gdb_fwrite_int((wpt->garmin_data != NULL) ? wpt->garmin_data->colour : 0); /* colour */
+#else
+ gdb_fwrite_int(0); /* display */
+ gdb_fwrite_int(0); /* colour */
+#endif
+ gdb_fwrite_icon(wpt); /* icon */
+ gdb_fwrite_str("", -1); /* city */
+ gdb_fwrite_str("", -1); /* state */
+ gdb_fwrite_str("", -1); /* facility */
+ gdb_fwrite(zbuf, 1); /* unknown */
+ gdb_fwrite_alt(wpt->depth, unknown_alt); /* depth */
+
+ gdb_fwrite(zbuf, 3); /* three unknown bytes */
+ gdb_fwrite(zbuf, 4); /* four unknown bytes */
+
+ gdb_fwrite_str(wpt->notes, -1); /* notes */
+
+#if 0
+ if (gdb_opt_category != NULL) /* category */
+ i = gdb_category;
+ else
+ i = (wpt->garmin_data != NULL) ? wpt->garmin_data->category : 0;
+#else
+ i = gdb_category;
+#endif
+ gdb_fwrite_le(&i, 2);
+
+ gdb_fwrite(zbuf, 1); /* temperature flag */
+
+ if (wpt->creation_time != 0) /* creation time */
+ {
+ gdb_fwrite(&c1, 1);
+ gdb_fwrite_int(wpt->creation_time);
+ }
+ else
+ gdb_fwrite(&c0, 1);
+
+}
+
+static void
+gdb_write_waypt_cb(const waypoint *wpt) /* called by waypt_disp over all waypoints */
+{
+ int reclen;
+ size_t pos;
+
+ /* check for duplicate waypoints */
+ if (NULL != gdb_find_wpt_q_by_name((queue *)&gdb_hidden->waypoint_list, wpt->shortname))
+ return;
+
+ gdb_fwrite_int(0);
+ gdb_fwrite_str("W", 1);
+
+ pos = ftell(fout);
+ gdb_write_waypt(wpt, 0);
+ reclen = ftell(fout) - pos;
+
+ fseek(fout, pos - 5, SEEK_SET);
+ gdb_fwrite_int(reclen);
+
+ fseek(fout, pos + reclen, SEEK_SET);
+
+ route_add_wpt(gdb_hidden, waypt_dupe(wpt)); /* add tis point to our internal queue */
+}
+
+static void
+gdb_write_rtewpt_cb(const waypoint *wpt) /* called by waypt_disp (route points) */
+{
+ int reclen;
+ size_t pos;
+ waypoint *tmp;
+
+ tmp = gdb_find_wpt_q_by_name((queue *)&gdb_hidden->waypoint_list, wpt->shortname);
+ if (tmp == NULL)
+ {
+ tmp = find_waypt_by_name(wpt->shortname);
+
+ gdb_fwrite_int(0);
+ gdb_fwrite_str("W", 1);
+
+ pos = ftell(fout);
+ gdb_write_waypt(wpt, (tmp == NULL));
+ reclen = ftell(fout) - pos;
+
+ fseek(fout, pos - 5, SEEK_SET);
+ gdb_fwrite_int(reclen);
+
+ fseek(fout, pos + reclen, SEEK_SET);
+
+ route_add_wpt(gdb_hidden, waypt_dupe(wpt)); /* add tis point to our internal queue */
+ }
}
-/* %%% gobal callbacks %%% */
+/*******************************************************************************/
+/* %%% write routes %%% */
+/*-----------------------------------------------------------------------------*/
-static void gdb_rd_init(const char *fname)
+void
+gdb_write_route(const route_head *route, const waypoint **list, const int count)
{
+ int i, wpt_class;
+ char buff[128], zbuff[32], ffbuff[32];
+ waypoint *prev = NULL;
+ const char c0 = 0;
+ const char c1 = 1;
+ const char c3 = 3;
+ double maxlat = -90;
+ double minlat = +90;
+ double maxlon = -180;
+ double minlon = +180;
+ double maxalt = -unknown_alt;
+ double minalt = +unknown_alt;
+
+ memset(zbuff, 0, sizeof(zbuff));
+ memset(ffbuff, 0xFF, sizeof(ffbuff));
+
+ for (i = 0; i < count; i++)
+ {
+ const waypoint *wpt = list[i];
+
+ if (wpt->latitude > maxlat) maxlat = wpt->latitude;
+ if (wpt->latitude < minlat) minlat = wpt->latitude;
+ if (wpt->longitude > maxlon) maxlon = wpt->longitude;
+ if (wpt->longitude < minlon) minlon = wpt->longitude;
+ if (wpt->altitude != unknown_alt)
+ {
+ if (wpt->altitude > maxalt) maxalt = wpt->altitude;
+ if (wpt->altitude < minalt) minalt = wpt->altitude;
+ }
+ }
+
+ if (route->rte_name == NULL)
+ {
+ snprintf(buff, sizeof(buff), "Route%04d", route->rte_num);
+ gdb_fwrite_str(buff, -1);
+ }
+ else
+ gdb_fwrite_str(route->rte_name, -1);
+
+ gdb_fwrite(&c0, 1); /* auto_name */
+
+ if (count == 1) gdb_fwrite(&c1, 1); /* skip max data */
+ else
+ {
+ gdb_fwrite(&c0, 1); /* ??? */
+ gdb_fwrite_int(GPS_Math_Deg_To_Semi(maxlat)); /* maximum latitude over route */
+ gdb_fwrite_int(GPS_Math_Deg_To_Semi(maxlon)); /* maximum longitude over route */
+ gdb_fwrite_alt(maxalt, unknown_alt); /* maximum altitude over route */
+
+ gdb_fwrite_int(GPS_Math_Deg_To_Semi(minlat)); /* minimum latitude over route */
+ gdb_fwrite_int(GPS_Math_Deg_To_Semi(minlon)); /* minimum longitude over route */
+ gdb_fwrite_alt(minalt, -unknown_alt); /* minimum altitude over route */
+ }
+
+ gdb_fwrite_int(count); /* number of points in route */
+
+ for (i = 0; i < count; i++)
+ {
+ const waypoint *wpt = list[i];
+
+ wpt_class = gdb_detect_rtept_class(wpt);
+
+ if (prev != NULL)
+ {
+ gdb_fwrite_int(2); /* route link details */
+
+ gdb_fwrite_int(GPS_Math_Deg_To_Semi(prev->latitude)); /* ilink step 1 (end point 1) */
+ gdb_fwrite_int(GPS_Math_Deg_To_Semi(prev->longitude));
+ gdb_fwrite_alt(prev->altitude, unknown_alt);
+
+ gdb_fwrite_int(GPS_Math_Deg_To_Semi(wpt->latitude)); /* ilink step 2 (end point 2) */
+ gdb_fwrite_int(GPS_Math_Deg_To_Semi(wpt->longitude));
+ gdb_fwrite_alt(wpt->altitude, unknown_alt);
+
+ if (wpt->latitude > prev->latitude) /* get maximum lat, lon and alt */
+ {
+ maxlat = wpt->latitude;
+ minlat = prev->latitude;
+ }
+ else
+ {
+ maxlat = prev->latitude;
+ minlat = wpt->latitude;
+ }
+ if (wpt->longitude > prev->longitude)
+ {
+ maxlon = wpt->longitude;
+ minlon = prev->longitude;
+ }
+ else
+ {
+ maxlon = prev->longitude;
+ minlon = wpt->longitude;
+ }
+ if (wpt->altitude != unknown_alt)
+ {
+ maxalt = wpt->altitude;
+ minalt = wpt->altitude;
+ }
+ else
+ {
+ maxalt = -unknown_alt;
+ minalt = +unknown_alt;
+ }
+ if (prev->altitude != unknown_alt)
+ {
+ if (prev->altitude > maxalt) maxalt = prev->altitude;
+ if (prev->altitude < minalt) minalt = prev->altitude;
+ }
+
+ gdb_fwrite(&c0, 1); /* ??? */
+
+ gdb_fwrite_int(GPS_Math_Deg_To_Semi(maxlat)); /* maximum coords & altitude */
+ gdb_fwrite_int(GPS_Math_Deg_To_Semi(maxlon));
+ gdb_fwrite_alt(maxalt, unknown_alt);
+
+ gdb_fwrite_int(GPS_Math_Deg_To_Semi(minlat)); /* minimum coords & altitude */
+ gdb_fwrite_int(GPS_Math_Deg_To_Semi(minlon));
+ gdb_fwrite_alt(minalt, -unknown_alt);
+
+ if (gdb_ver > 1)
+ gdb_fwrite(ffbuff, 8);
+ }
+
+ gdb_fwrite_str(wpt->shortname, -1); /* short name */
+
+ gdb_fwrite_int(wpt_class); /* class */
+ gdb_fwrite_str("", -1); /* country */
+
+ gdb_fwrite(zbuff, 4); /* subclass part 1 */
+ gdb_fwrite(ffbuff, 12); /* subclass part 2 */
+ gdb_fwrite(zbuff, 2); /* subclass part 3 */
+ gdb_fwrite(ffbuff, 4); /* unknown */
+
+ gdb_fwrite(&c0, 1); /* unknown value or string */
+ gdb_fwrite(&c3, 1); /* unknown 18 bytes starting with 0x03 */
+ gdb_fwrite(zbuff, 3);
+ gdb_fwrite(ffbuff, 4);
+ gdb_fwrite(zbuff, 10);
+
+ prev = (waypoint *)wpt;
+ }
+
+ gdb_fwrite_int(0); /* Zero interlink steps */
+ gdb_fwrite(&c1, 1);
+
+ if (gdb_ver > 1)
+ gdb_fwrite(ffbuff, 8);
+
+ gdb_fwrite(&c0, 1);
+}
+
+static void
+gdb_write_route_cb(const route_head *route)
+{
+ int reclen;
+ size_t pos;
+ int count;
+ waypoint **list;
+
+ list = gdb_route_point_list(route, &count);
+ if (count == 0) return; /* don't write empty routes */
+
+ gdb_fwrite_int(0);
+ gdb_fwrite_str("R", 1);
+
+ pos = ftell(fout);
+ gdb_write_route(route, (const waypoint**)list, count);
+ reclen = ftell(fout) - pos;
+
+ fseek(fout, pos - 5, SEEK_SET);
+ gdb_fwrite_int(reclen);
+
+ fseek(fout, pos + reclen, SEEK_SET);
+
+ xfree(list);
+}
+
+/*******************************************************************************/
+/* %%% write tracks %%% */
+/*-----------------------------------------------------------------------------*/
+
+void
+gdb_write_track(const route_head *track)
+{
+ char buff[128];
+ const char c0 = 0;
+ const char c1 = 1;
+ queue *elem, *tmp;
+ int count = track->rte_waypt_ct;
+
+ if (track->rte_name == NULL)
+ snprintf(buff, sizeof(buff), "Track%04d", track->rte_num);
+ else
+ strncpy(buff, track->rte_name, sizeof(buff));
+
+ gdb_fwrite_str(buff, -1);
+ gdb_fwrite(&c0, 1); /* display */
+ gdb_fwrite_int(0); /* xcolour */
+ gdb_fwrite_int(count);
+
+ QUEUE_FOR_EACH((queue *)&track->waypoint_list, elem, tmp)
+ {
+ waypoint *wpt = (waypoint *)elem;
+
+ gdb_fwrite_int(GPS_Math_Deg_To_Semi(wpt->latitude));
+ gdb_fwrite_int(GPS_Math_Deg_To_Semi(wpt->longitude));
+ gdb_fwrite_alt(wpt->altitude, unknown_alt); /* altitude */
+
+
+ if (wpt->creation_time != 0) /* creation time */
+ {
+ gdb_fwrite(&c1, 1);
+ gdb_fwrite_int(wpt->creation_time);
+ }
+ else
+ gdb_fwrite(&c0, 1);
+
+ gdb_fwrite_alt(wpt->depth, unknown_alt); /* depth */
+ gdb_fwrite(&c0, 1); /* temperature */
+ }
+ gdb_fwrite(&c0, 1);
+}
+
+static void
+gdb_write_track_cb(const route_head *track) /* called from track_disp_all */
+{
+ int reclen;
+ size_t pos;
+
+ if (track->rte_waypt_ct <= 0) return; /* don't write empty tracks */
+
+ gdb_fwrite_int(0);
+ gdb_fwrite_str("T", 1);
+
+ pos = ftell(fout);
+
+ gdb_write_track(track);
+
+ reclen = ftell(fout) - pos;
+ fseek(fout, pos - 5, SEEK_SET);
+ gdb_fwrite_int(reclen);
+
+ fseek(fout, pos + reclen, SEEK_SET);
+}
+
+/*******************************************************************************/
+
+void
+gdb_write_data(void)
+{
+ char c1 = 1;
+
+ gdb_hidden = route_head_alloc(); /* contains all written waypts & rtepts */
+ track_add_head(gdb_hidden); /* tracks comes later and we drop this before */
+
+ if (doing_wpts) waypt_disp_all(gdb_write_waypt_cb);
+ if (doing_rtes)
+ {
+
+ if (gdb_via == 0)
+ {
+ /* find out all route points we have to write as a "HIDDEN CLASS" waypoint */
+ route_disp_all(NULL, NULL, gdb_write_rtewpt_cb);
+ }
+ route_disp_all(gdb_write_route_cb, NULL, NULL);
+ }
+
+ track_del_head(gdb_hidden); /* vaporize our temporary queue */
+
+ if (doing_trks) track_disp_all(gdb_write_track_cb, NULL, NULL);
+
+ gdb_fwrite_int(2); /* finalize gdb with empty map segment */
+ gdb_fwrite_str("V", -1);
+ gdb_fwrite(&c1, 1);
+}
+
+/*******************************************************************************/
+
+void
+gdb_init_opts(const char op) /* 1 = read; 2 = write */
+{
+ gdb_via = 0;
+ gdb_category = 0;
+ gdb_ver = 2;
+
+ if (gdb_opt_via != NULL) /* opt_via present in both ops */
+ {
+ if ((case_ignore_strcmp(gdb_opt_via, GDB_OPT_VIA) == 0) ||
+ (*gdb_opt_via == '\0'))
+ gdb_via = 1;
+ else
+ gdb_via = atoi(gdb_opt_via);
+ }
+
+ if (op & 2) /* writer opts */
+ {
+ if ((gdb_opt_category != NULL) &&
+ (case_ignore_strcmp(gdb_opt_category, GDB_OPT_CATEGORY) != 0) &&
+ (*gdb_opt_category != '\0'))
+ {
+ gdb_category = atoi(gdb_opt_category);
+ if ((gdb_category < 1) || (gdb_category > 16))
+ fatal(MYNAME ": Unsupported category \"%s\"!\n", gdb_opt_category);
+ gdb_category = 1 << --gdb_category;
+ }
+
+ gdb_ver = atoi(gdb_opt_ver);
+ if ((gdb_ver < GDB_VER_MIN) || (gdb_ver > GDB_VER_MAX))
+ fatal(MYNAME ": Unsupported version \"%s\"!\n", gdb_opt_ver);
+ }
+}
+
+/*******************************************************************************/
+/* %%% global cb's %%% */
+/*******************************************************************************/
+
+static void
+gdb_rd_init(const char *fname)
+{
+ gdb_init_opts(1);
+
fin_name = xstrdup(fname);
fin = xfopen(fname, "rb", MYNAME);
- gdb_hidden = route_head_alloc();
- track_add_head(gdb_hidden);
}
-static void gdb_rd_deinit(void)
+static void
+gdb_wr_init(const char *fname)
+{
+ gdb_init_opts(2);
+
+ fout_name = xstrdup(fname);
+ fout = xfopen(fname, "wb", MYNAME);
+}
+
+static void
+gdb_rd_deinit(void)
{
- track_del_head(gdb_hidden);
fclose(fin);
xfree(fin_name);
+ fin_name = NULL;
+}
+
+static void
+gdb_wr_deinit(void)
+{
+ fclose(fout);
+ xfree(fout_name);
+ fout_name = NULL;
}
-static void gdb_read(void)
+static void
+gdb_read(void)
{
gdb_read_file_header();
gdb_read_data();
}
+static void
+gdb_write(void)
+{
+ gdb_write_file_header(NULL);
+ gdb_write_data();
+}
+
+/*******************************************************************************/
ff_vecs_t gdb_vecs = {
ff_type_file,
- { ff_cap_read, ff_cap_read, ff_cap_read }, /* FF_CAP_RW_ALL, !!! I hope !!! */
+ FF_CAP_RW_ALL,
gdb_rd_init,
- NULL, /* gdb_wr_init, */
+ gdb_wr_init,
gdb_rd_deinit,
- NULL, /* gdb_wr_deinit, */
+ gdb_wr_deinit,
gdb_read,
- NULL, /* gdb_write, */
+ gdb_write,
NULL,
- NULL /* gdb_args */
+ gdb_args
};
+
+/*******************************************************************************/
<sym>Residence</sym>
</rtept>
<rtept lat="50.492606163" lon="12.105431557">
+<time>2005-04-26T14:27:21Z</time>
<name>416</name>
+ <desc>Fahren Sie auf die Luis-Ferdinand-Schönherr-Strasse nach Norden</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.492606163" lon="12.105431557">
+<time>2005-04-26T14:27:21Z</time>
<name>417</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.494279861" lon="12.105131149">
+<time>2005-04-26T14:27:21Z</time>
<name>418</name>
+ <desc>Biegen Sie rechts ab auf die Liebknechtstrasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.493836962" lon="12.106101271">
+<time>2005-04-26T14:27:21Z</time>
<name>419</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.493837046" lon="12.106101019">
<time>2005-02-26T09:03:15Z</time>
<sym>Golf Course</sym>
</rtept>
<rtept lat="50.493836962" lon="12.106101271">
+<time>2005-04-26T14:27:21Z</time>
<name>420</name>
+ <desc>Fahren Sie auf die Liebknechtstrasse nach Südosten</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.493378639" lon="12.107105255">
+<time>2005-04-26T14:27:21Z</time>
<name>421</name>
+ <desc>Biegen Sie links ab auf die Jahnstrasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.493662786" lon="12.107152529">
+<time>2005-04-26T14:27:21Z</time>
<name>422</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.493662870" lon="12.107152529">
<time>2005-02-26T09:02:20Z</time>
<sym>Golf Course</sym>
</rtept>
<rtept lat="50.493662786" lon="12.107152529">
+<time>2005-04-26T14:27:21Z</time>
<name>423</name>
+ <desc>Fahren Sie auf die Jahnstrasse nach Norden</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.494666100" lon="12.107319832">
+<time>2005-04-26T14:27:21Z</time>
<name>424</name>
+ <desc>Biegen Sie links ab auf die Neundorfer Strasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.494666100" lon="12.106633186">
+<time>2005-04-26T14:27:21Z</time>
<name>425</name>
+ <desc>Biegen Sie rechts ab auf die Scharnhorststrasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.496554375" lon="12.105002403">
+<time>2005-04-26T14:27:21Z</time>
<name>426</name>
+ <desc>Biegen Sie rechts ab auf die Schminckestrasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.497756004" lon="12.106332779">
+<time>2005-04-26T14:27:21Z</time>
<name>427</name>
+ <desc>Biegen Sie links ab auf die Kopernikusstrasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.499987602" lon="12.103672028">
+<time>2005-04-26T14:27:21Z</time>
<name>428</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.499987602" lon="12.103672028">
+<time>2005-04-26T14:27:21Z</time>
<name>429</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.500202179" lon="12.103500366">
+<time>2005-04-26T14:27:21Z</time>
<name>430</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.502090454" lon="12.102470398">
+<time>2005-04-26T14:27:21Z</time>
<name>431</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.503549576" lon="12.099037170">
+<time>2005-04-26T14:27:21Z</time>
<name>432</name>
+ <desc>Ordnen Sie sich rechts ein in Richtung Talstrasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.510201454" lon="12.092342377">
+<time>2005-04-26T14:27:21Z</time>
<name>433</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.512003899" lon="12.090926170">
+<time>2005-04-26T14:27:21Z</time>
<name>434</name>
+ <desc>Biegen Sie rechts ab auf die Zwoschwitzer Strasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.512475967" lon="12.091741562">
+<time>2005-04-26T14:27:21Z</time>
<name>435</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.520200729" lon="12.091612816">
+<time>2005-04-26T14:27:21Z</time>
<name>436</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.523333549" lon="12.092986107">
+<time>2005-04-26T14:27:21Z</time>
<name>437</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.524277687" lon="12.093672752">
+<time>2005-04-26T14:27:21Z</time>
<name>438</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.525264740" lon="12.093973160">
+<time>2005-04-26T14:27:21Z</time>
<name>439</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.525865555" lon="12.094359398">
+<time>2005-04-26T14:27:21Z</time>
<name>440</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.526509285" lon="12.094831467">
+<time>2005-04-26T14:27:21Z</time>
<name>441</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.530071259" lon="12.098007202">
+<time>2005-04-26T14:27:21Z</time>
<name>442</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.534362793" lon="12.104401588">
+<time>2005-04-26T14:27:21Z</time>
<name>443</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.534491539" lon="12.104487419">
+<time>2005-04-26T14:27:21Z</time>
<name>444</name>
+ <desc>Biegen Sie links ab auf die An Der Schöpsdrehe</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.534920692" lon="12.103457451">
+<time>2005-04-26T14:27:21Z</time>
<name>445</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.535736084" lon="12.100839615">
+<time>2005-04-26T14:27:21Z</time>
<name>446</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.535778999" lon="12.100667953">
+<time>2005-04-26T14:27:21Z</time>
<name>447</name>
+ <desc>Biegen Sie rechts ab auf die Elsterberger Strasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.537710190" lon="12.102599144">
+<time>2005-04-26T14:27:21Z</time>
<name>448</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.544619560" lon="12.105388641">
+<time>2005-04-26T14:27:21Z</time>
<name>449</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.591139793" lon="12.138476372">
+<time>2005-04-26T14:27:21Z</time>
<name>450</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.591440201" lon="12.138905525">
+<time>2005-04-26T14:27:21Z</time>
<name>451</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.605859756" lon="12.154955864">
+<time>2005-04-26T14:27:21Z</time>
<name>452</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.605387688" lon="12.160363197">
+<time>2005-04-26T14:27:21Z</time>
<name>453</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.607104301" lon="12.168259621">
+<time>2005-04-26T14:27:21Z</time>
<name>454</name>
+ <desc>Biegen Sie rechts ab auf die Robert-Schenker-Strasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.606160164" lon="12.168302536">
+<time>2005-04-26T14:27:21Z</time>
<name>455</name>
+ <desc>Biegen Sie links ab auf die Rosa-Luxemburg-Strasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.607061386" lon="12.172594070">
+<time>2005-04-26T14:27:21Z</time>
<name>456</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.609421730" lon="12.175040245">
+<time>2005-04-26T14:27:21Z</time>
<name>457</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.610795189" lon="12.173802238">
+<time>2005-04-26T14:27:21Z</time>
<name>458</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.610795273" lon="12.173802154">
<time>2005-02-26T08:59:59Z</time>
<sym>Golf Course</sym>
</rtept>
<rtept lat="50.610795189" lon="12.173802238">
+<time>2005-04-26T14:27:22Z</time>
<name>459</name>
+ <desc>Fahren Sie auf die Piehlerstrasse nach Nordwesten</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.612468719" lon="12.168731689">
+<time>2005-04-26T14:27:22Z</time>
<name>460</name>
+ <desc>Biegen Sie rechts ab auf die Greizer Strasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.616717339" lon="12.170190811">
+<time>2005-04-26T14:27:22Z</time>
<name>461</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.619249344" lon="12.172937393">
+<time>2005-04-26T14:27:22Z</time>
<name>462</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.623326302" lon="12.176756859">
+<time>2005-04-26T14:27:22Z</time>
<name>463</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.623583794" lon="12.180147171">
+<time>2005-04-26T14:27:22Z</time>
<name>464</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.633797646" lon="12.192077637">
+<time>2005-04-26T14:27:22Z</time>
<name>465</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.634012222" lon="12.192249298">
+<time>2005-04-26T14:27:22Z</time>
<name>466</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.637145042" lon="12.191991806">
+<time>2005-04-26T14:27:22Z</time>
<name>467</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.646672249" lon="12.195553780">
+<time>2005-04-26T14:27:22Z</time>
<name>468</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.647916794" lon="12.194480896">
+<time>2005-04-26T14:27:22Z</time>
<name>469</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.647959709" lon="12.194480896">
+<time>2005-04-26T14:27:22Z</time>
<name>470</name>
+ <desc>Halten Sie sich rechts in Richtung Carolinenstrasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.655169487" lon="12.198171616">
+<time>2005-04-26T14:27:22Z</time>
<name>471</name>
+ <desc>Biegen Sie rechts ab auf die Gartenweg</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.654611588" lon="12.199459076">
+<time>2005-04-26T14:27:22Z</time>
<name>472</name>
+ <desc>Biegen Sie links ab auf die B94</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.655384064" lon="12.201776505">
+<time>2005-04-26T14:27:22Z</time>
<name>473</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.655512810" lon="12.202463150">
+<time>2005-04-26T14:27:22Z</time>
<name>474</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.655469894" lon="12.202720642">
+<time>2005-04-26T14:27:22Z</time>
<name>475</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.654911995" lon="12.204480171">
+<time>2005-04-26T14:27:22Z</time>
<name>476</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.654762965" lon="12.204956934">
+<time>2005-04-26T14:27:22Z</time>
<name>477</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.654763049" lon="12.204956766">
<time>2005-02-26T08:57:04Z</time>
<sym>Golf Course</sym>
</rtept>
<rtept lat="50.654762965" lon="12.204956934">
+<time>2005-04-26T14:27:22Z</time>
<name>478</name>
+ <desc>Fahren Sie auf die August-Bebel-Strasse nach Südosten</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.653924942" lon="12.207655907">
+<time>2005-04-26T14:27:22Z</time>
<name>479</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.652594566" lon="12.211861610">
+<time>2005-04-26T14:27:22Z</time>
<name>480</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.652036667" lon="12.227139473">
+<time>2005-04-26T14:27:22Z</time>
<name>481</name>
+ <desc>Biegen Sie links ab auf die Werdauer Strasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.652594566" lon="12.227997780">
+<time>2005-04-26T14:27:22Z</time>
<name>482</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.653667450" lon="12.231731415">
+<time>2005-04-26T14:27:22Z</time>
<name>483</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.655684471" lon="12.242288589">
+<time>2005-04-26T14:27:22Z</time>
<name>484</name>
+ <desc>Halten Sie sich rechts in Richtung Werdauer Strasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.656456947" lon="12.247138023">
+<time>2005-04-26T14:27:22Z</time>
<name>485</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.657229424" lon="12.248253822">
+<time>2005-04-26T14:27:22Z</time>
<name>486</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.668387413" lon="12.262930870">
+<time>2005-04-26T14:27:22Z</time>
<name>487</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.671992302" lon="12.270097733">
+<time>2005-04-26T14:27:22Z</time>
<name>488</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.675039291" lon="12.277135849">
+<time>2005-04-26T14:27:22Z</time>
<name>489</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.675640106" lon="12.282586098">
+<time>2005-04-26T14:27:22Z</time>
<name>490</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.675683022" lon="12.282757759">
+<time>2005-04-26T14:27:22Z</time>
<name>491</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.678043365" lon="12.292113304">
+<time>2005-04-26T14:27:22Z</time>
<name>492</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.684738159" lon="12.316360474">
+<time>2005-04-26T14:27:22Z</time>
<name>493</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.695896149" lon="12.340135574">
+<time>2005-04-26T14:27:22Z</time>
<name>494</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.697956085" lon="12.341938019">
+<time>2005-04-26T14:27:22Z</time>
<name>495</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.698599815" lon="12.344083786">
+<time>2005-04-26T14:27:22Z</time>
<name>496</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.698857307" lon="12.344899178">
+<time>2005-04-26T14:27:22Z</time>
<name>497</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.706324577" lon="12.361764908">
+<time>2005-04-26T14:27:22Z</time>
<name>498</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.714221001" lon="12.371807098">
+<time>2005-04-26T14:27:22Z</time>
<name>499</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.714993477" lon="12.372364998">
+<time>2005-04-26T14:27:22Z</time>
<name>500</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.716238022" lon="12.373266220">
+<time>2005-04-26T14:27:22Z</time>
<name>501</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.724606514" lon="12.373137474">
+<time>2005-04-26T14:27:22Z</time>
<name>502</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.728297234" lon="12.374081612">
+<time>2005-04-26T14:27:22Z</time>
<name>503</name>
+ <desc>Halten Sie sich links in Richtung Marienstrasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.731773376" lon="12.374167442">
+<time>2005-04-26T14:27:22Z</time>
<name>504</name>
+ <desc>Biegen Sie links ab auf die Uferstrasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.739798546" lon="12.376356125">
+<time>2005-04-26T14:27:22Z</time>
<name>505</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.775847435" lon="12.368073463">
+<time>2005-04-26T14:27:22Z</time>
<name>506</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.812239647" lon="12.388501167">
+<time>2005-04-26T14:27:22Z</time>
<name>507</name>
+ <desc>Biegen Sie links ab auf die Querstrasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.812325478" lon="12.387084961">
+<time>2005-04-26T14:27:22Z</time>
<name>508</name>
+ <desc>Biegen Sie rechts ab auf die Carthäuserstrasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.812454224" lon="12.386956215">
+<time>2005-04-26T14:27:22Z</time>
<name>509</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.813097954" lon="12.386569977">
+<time>2005-04-26T14:27:22Z</time>
<name>510</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.814642906" lon="12.385797501">
+<time>2005-04-26T14:27:22Z</time>
<name>511</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.816531181" lon="12.385239601">
+<time>2005-04-26T14:27:22Z</time>
<name>512</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.817217827" lon="12.385926247">
+<time>2005-04-26T14:27:22Z</time>
<name>513</name>
+ <desc>Halten Sie sich links in Richtung S54</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.818977356" lon="12.385969162">
+<time>2005-04-26T14:27:22Z</time>
<name>514</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.825457573" lon="12.387986183">
+<time>2005-04-26T14:27:22Z</time>
<name>515</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.826058388" lon="12.388329506">
+<time>2005-04-26T14:27:22Z</time>
<name>516</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.842709541" lon="12.393994331">
+<time>2005-04-26T14:27:22Z</time>
<name>517</name>
+ <desc>Biegen Sie rechts ab auf die Leipziger Strasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.844254494" lon="12.397599220">
+<time>2005-04-26T14:27:22Z</time>
<name>518</name>
+ <desc>Biegen Sie rechts ab auf die Leipziger Strasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.842108727" lon="12.400431633">
+<time>2005-04-26T14:27:22Z</time>
<name>519</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.841979980" lon="12.400732040">
+<time>2005-04-26T14:27:22Z</time>
<name>520</name>
+ <desc>Biegen Sie links ab auf die Ponitzer Strasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.843696594" lon="12.406182289">
+<time>2005-04-26T14:27:22Z</time>
<name>521</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.843997002" lon="12.408328056">
+<time>2005-04-26T14:27:22Z</time>
<name>522</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.844125664" lon="12.408756875">
+<time>2005-04-26T14:27:22Z</time>
<name>523</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.844125748" lon="12.408757210">
<time>2005-02-26T09:10:47Z</time>
<sym>Golf Course</sym>
</rtept>
<rtept lat="50.844125664" lon="12.408756875">
+<time>2005-04-26T14:27:22Z</time>
<name>524</name>
+ <desc>Fahren Sie auf die Gosel nach Nordosten</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.844254494" lon="12.409186363">
+<time>2005-04-26T14:27:22Z</time>
<name>525</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.846185684" lon="12.412233353">
+<time>2005-04-26T14:27:22Z</time>
<name>526</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.856056213" lon="12.423348427">
+<time>2005-04-26T14:27:22Z</time>
<name>527</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.858330727" lon="12.424507141">
+<time>2005-04-26T14:27:22Z</time>
<name>528</name>
+ <desc>Biegen Sie rechts ab auf die Gössnitzer Strasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.860562325" lon="12.427039146">
+<time>2005-04-26T14:27:22Z</time>
<name>529</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.872192383" lon="12.434377670">
+<time>2005-04-26T14:27:22Z</time>
<name>530</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.875239372" lon="12.435235977">
+<time>2005-04-26T14:27:22Z</time>
<name>531</name>
+ <desc>Biegen Sie links ab auf die Altenburger Strasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.876870155" lon="12.434163094">
+<time>2005-04-26T14:27:22Z</time>
<name>532</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.877340548" lon="12.433888670">
+<time>2005-04-26T14:27:22Z</time>
<name>533</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.877340632" lon="12.433888670">
<name>3</name>
<sym>Waypoint</sym>
</rtept>
<rtept lat="50.877340548" lon="12.433888670">
+<time>2005-04-26T14:27:23Z</time>
<name>534</name>
+ <desc>Fahren Sie auf die Altenburger Strasse nach Norden</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.879616737" lon="12.432918549">
+<time>2005-04-26T14:27:23Z</time>
<name>535</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.880904198" lon="12.432188988">
+<time>2005-04-26T14:27:23Z</time>
<name>536</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.881419182" lon="12.431759834">
+<time>2005-04-26T14:27:23Z</time>
<name>537</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.887727737" lon="12.430858612">
+<time>2005-04-26T14:27:23Z</time>
<name>538</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.888371468" lon="12.432703972">
+<time>2005-04-26T14:27:23Z</time>
<name>539</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.888543129" lon="12.433948517">
+<time>2005-04-26T14:27:23Z</time>
<name>540</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.901160240" lon="12.440814972">
+<time>2005-04-26T14:27:23Z</time>
<name>541</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.902791023" lon="12.440428734">
+<time>2005-04-26T14:27:23Z</time>
<name>542</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.905494690" lon="12.439956665">
+<time>2005-04-26T14:27:23Z</time>
<name>543</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.910258293" lon="12.441716194">
+<time>2005-04-26T14:27:23Z</time>
<name>544</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.911631584" lon="12.442531586">
+<time>2005-04-26T14:27:23Z</time>
<name>545</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.920085907" lon="12.444977760">
+<time>2005-04-26T14:27:23Z</time>
<name>546</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.924978256" lon="12.443475723">
+<time>2005-04-26T14:27:23Z</time>
<name>547</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.933046341" lon="12.429485321">
+<time>2005-04-26T14:27:23Z</time>
<name>548</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.935878754" lon="12.426309586">
+<time>2005-04-26T14:27:23Z</time>
<name>549</name>
+ <desc>Biegen Sie links ab auf die Hauptstrasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.933132172" lon="12.420730591">
+<time>2005-04-26T14:27:23Z</time>
<name>550</name>
+ <desc>Biegen Sie rechts ab auf die K61</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.933818817" lon="12.419013977">
+<time>2005-04-26T14:27:23Z</time>
<name>551</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.938711166" lon="12.414765358">
+<time>2005-04-26T14:27:23Z</time>
<name>552</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.941715240" lon="12.413306236">
+<time>2005-04-26T14:27:23Z</time>
<name>553</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.942659378" lon="12.412362099">
+<time>2005-04-26T14:27:23Z</time>
<name>554</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.949354172" lon="12.405452728">
+<time>2005-04-26T14:27:23Z</time>
<name>555</name>
+ <desc>Biegen Sie rechts ab auf die Schmöllner Strasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.956048965" lon="12.410302162">
+<time>2005-04-26T14:27:23Z</time>
<name>556</name>
+ <desc>Halten Sie sich rechts in Richtung Straße</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.964955157" lon="12.435919270">
+<time>2005-04-26T14:27:23Z</time>
<name>557</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.964955240" lon="12.435919438">
<time>2005-06-24T00:50:24Z</time>
<sym>Golf Course</sym>
</rtept>
<rtept lat="50.964955157" lon="12.435919270">
+<time>2005-04-26T14:27:23Z</time>
<name>558</name>
+ <desc>Fahren Sie auf die Straße nach Nordosten</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.999994278" lon="12.470340729">
+<time>2005-04-26T14:27:23Z</time>
<name>559</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="50.999994278" lon="12.470340729">
+<time>2005-04-26T14:27:23Z</time>
<name>560</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.011323929" lon="12.454934120">
+<time>2005-04-26T14:27:23Z</time>
<name>561</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.023340225" lon="12.456436157">
+<time>2005-04-26T14:27:23Z</time>
<name>562</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.025185585" lon="12.457680702">
+<time>2005-04-26T14:27:23Z</time>
<name>563</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.026730537" lon="12.458109856">
+<time>2005-04-26T14:27:23Z</time>
<name>564</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.037459373" lon="12.458624840">
+<time>2005-04-26T14:27:23Z</time>
<name>565</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.043510437" lon="12.455277443">
+<time>2005-04-26T14:27:23Z</time>
<name>566</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.043682098" lon="12.455277443">
+<time>2005-04-26T14:27:23Z</time>
<name>567</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.050333977" lon="12.454290390">
+<time>2005-04-26T14:27:23Z</time>
<name>568</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.050977707" lon="12.454075813">
+<time>2005-04-26T14:27:23Z</time>
<name>569</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.052565575" lon="12.453346252">
+<time>2005-04-26T14:27:23Z</time>
<name>570</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.053166389" lon="12.453131676">
+<time>2005-04-26T14:27:23Z</time>
<name>571</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.053895950" lon="12.453432083">
+<time>2005-04-26T14:27:23Z</time>
<name>572</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.054925919" lon="12.453861237">
+<time>2005-04-26T14:27:23Z</time>
<name>573</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.058444977" lon="12.454719543">
+<time>2005-04-26T14:27:23Z</time>
<name>574</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.062393188" lon="12.454032898">
+<time>2005-04-26T14:27:23Z</time>
<name>575</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.065225601" lon="12.453517914">
+<time>2005-04-26T14:27:23Z</time>
<name>576</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.072306633" lon="12.460212708">
+<time>2005-04-26T14:27:23Z</time>
<name>577</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.075139046" lon="12.463688850">
+<time>2005-04-26T14:27:23Z</time>
<name>578</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.081104279" lon="12.465276718">
+<time>2005-04-26T14:27:23Z</time>
<name>579</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.086254120" lon="12.468323708">
+<time>2005-04-26T14:27:23Z</time>
<name>580</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.088700294" lon="12.469439507">
+<time>2005-04-26T14:27:23Z</time>
<name>581</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.093463898" lon="12.473216057">
+<time>2005-04-26T14:27:23Z</time>
<name>582</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.107110977" lon="12.489309311">
+<time>2005-04-26T14:27:23Z</time>
<name>583</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.110973358" lon="12.490983009">
+<time>2005-04-26T14:27:23Z</time>
<name>584</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.118955612" lon="12.484116554">
+<time>2005-04-26T14:27:23Z</time>
<name>585</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.120371819" lon="12.485876083">
+<time>2005-04-26T14:27:23Z</time>
<name>586</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.122260094" lon="12.489266396">
+<time>2005-04-26T14:27:23Z</time>
<name>587</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.127624512" lon="12.504329681">
+<time>2005-04-26T14:27:23Z</time>
<name>588</name>
+ <desc>Biegen Sie links ab auf die Leipziger Strasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.131916046" lon="12.505788803">
+<time>2005-04-26T14:27:23Z</time>
<name>589</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.133460999" lon="12.506861687">
+<time>2005-04-26T14:27:23Z</time>
<name>590</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.135735512" lon="12.508449554">
+<time>2005-04-26T14:27:23Z</time>
<name>591</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.191182137" lon="12.470211983">
+<time>2005-04-26T14:27:23Z</time>
<name>592</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.194314957" lon="12.462058067">
+<time>2005-04-26T14:27:23Z</time>
<name>593</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.230278015" lon="12.388458252">
+<time>2005-04-26T14:27:23Z</time>
<name>594</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.275467873" lon="12.383222580">
+<time>2005-04-26T14:27:23Z</time>
<name>595</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.299843788" lon="12.376141548">
+<time>2005-04-26T14:27:23Z</time>
<name>596</name>
+ <desc>Fahren Sie rechts ab auf die Prinz-Eugen-Strasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.301903725" lon="12.375884056">
+<time>2005-04-26T14:27:23Z</time>
<name>597</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.302890778" lon="12.375154495">
+<time>2005-04-26T14:27:23Z</time>
<name>598</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.303405762" lon="12.374296188">
+<time>2005-04-26T14:27:23Z</time>
<name>599</name>
+ <desc>Biegen Sie rechts ab auf die Wolfgang-Heinze-Strasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.304135323" lon="12.374124527">
+<time>2005-04-26T14:27:23Z</time>
<name>600</name>
+ <desc>Biegen Sie rechts ab auf die Meusdorfer Strasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.309285164" lon="12.387299538">
+<time>2005-04-26T14:27:23Z</time>
<name>601</name>
+ <desc>Biegen Sie rechts ab auf die Arno-Nitzsche-Strasse</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.310272217" lon="12.396268845">
+<time>2005-04-26T14:27:23Z</time>
<name>602</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.314005852" lon="12.406268120">
+<time>2005-04-26T14:27:23Z</time>
<name>603</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.314606667" lon="12.408971786">
+<time>2005-04-26T14:27:23Z</time>
<name>604</name>
+ <desc>Ordnen Sie sich rechts ein in Richtung Strasse Des 18. Oktober</desc>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.314536594" lon="12.409158535">
+<time>2005-04-26T14:27:23Z</time>
<name>605</name>
+ <sym>Waypoint</sym>
</rtept>
<rtept lat="51.314520836" lon="12.409143448">
<time>2005-06-24T00:36:57Z</time>